diff --git a/server/handlers.go b/server/handlers.go
index eb65f490..660a01c4 100644
--- a/server/handlers.go
+++ b/server/handlers.go
@@ -19,6 +19,7 @@ import (
 	jose "gopkg.in/square/go-jose.v2"
 
 	"github.com/dexidp/dex/connector"
+	"github.com/dexidp/dex/pkg/groups"
 	"github.com/dexidp/dex/server/internal"
 	"github.com/dexidp/dex/storage"
 )
@@ -491,18 +492,28 @@ func (s *Server) handleApproval(w http.ResponseWriter, r *http.Request) {
 		return
 	}
 
+	client, err := s.storage.GetClient(authReq.ClientID)
+	if err != nil {
+		s.logger.Errorf("Failed to get client %q: %v", authReq.ClientID, err)
+		s.renderError(r, w, http.StatusInternalServerError, "Failed to retrieve client.")
+		return
+	}
+
+	if len(client.AllowedGroups) > 0 {
+		authReq.Claims.Groups = groups.Filter(authReq.Claims.Groups, client.AllowedGroups)
+		if len(authReq.Claims.Groups) == 0 {
+			s.logger.Errorf("user not in allowed groups: %v", client.AllowedGroups)
+			s.renderError(r, w, http.StatusInternalServerError, "User not in allowed groups.")
+			return
+		}
+	}
+
 	switch r.Method {
 	case http.MethodGet:
 		if s.skipApproval {
 			s.sendCodeResponse(w, r, authReq)
 			return
 		}
-		client, err := s.storage.GetClient(authReq.ClientID)
-		if err != nil {
-			s.logger.Errorf("Failed to get client %q: %v", authReq.ClientID, err)
-			s.renderError(r, w, http.StatusInternalServerError, "Failed to retrieve client.")
-			return
-		}
 		if err := s.templates.approval(r, w, authReq.ID, authReq.Claims.Username, client.Name, authReq.Scopes); err != nil {
 			s.logger.Errorf("Server template error: %v", err)
 		}
diff --git a/storage/kubernetes/types.go b/storage/kubernetes/types.go
index 07e25084..8aefe485 100644
--- a/storage/kubernetes/types.go
+++ b/storage/kubernetes/types.go
@@ -197,6 +197,8 @@ type Client struct {
 
 	Name    string `json:"name,omitempty"`
 	LogoURL string `json:"logoURL,omitempty"`
+
+	AllowedGroups []string `json:"allowedGroups,omitempty"`
 }
 
 // ClientList is a list of Clients.
@@ -216,25 +218,27 @@ func (cli *client) fromStorageClient(c storage.Client) Client {
 			Name:      cli.idToName(c.ID),
 			Namespace: cli.namespace,
 		},
-		ID:           c.ID,
-		Secret:       c.Secret,
-		RedirectURIs: c.RedirectURIs,
-		TrustedPeers: c.TrustedPeers,
-		Public:       c.Public,
-		Name:         c.Name,
-		LogoURL:      c.LogoURL,
+		ID:            c.ID,
+		Secret:        c.Secret,
+		RedirectURIs:  c.RedirectURIs,
+		TrustedPeers:  c.TrustedPeers,
+		Public:        c.Public,
+		Name:          c.Name,
+		LogoURL:       c.LogoURL,
+		AllowedGroups: c.AllowedGroups,
 	}
 }
 
 func toStorageClient(c Client) storage.Client {
 	return storage.Client{
-		ID:           c.ID,
-		Secret:       c.Secret,
-		RedirectURIs: c.RedirectURIs,
-		TrustedPeers: c.TrustedPeers,
-		Public:       c.Public,
-		Name:         c.Name,
-		LogoURL:      c.LogoURL,
+		ID:            c.ID,
+		Secret:        c.Secret,
+		RedirectURIs:  c.RedirectURIs,
+		TrustedPeers:  c.TrustedPeers,
+		Public:        c.Public,
+		Name:          c.Name,
+		LogoURL:       c.LogoURL,
+		AllowedGroups: c.AllowedGroups,
 	}
 }
 
diff --git a/storage/storage.go b/storage/storage.go
index c308ac46..76ff386f 100644
--- a/storage/storage.go
+++ b/storage/storage.go
@@ -164,6 +164,8 @@ type Client struct {
 	// Name and LogoURL used when displaying this client to the end user.
 	Name    string `json:"name" yaml:"name"`
 	LogoURL string `json:"logoURL" yaml:"logoURL"`
+
+	AllowedGroups []string `json:"allowedGroups,omitempty" yaml:"allowedGroups,omitempty"`
 }
 
 // Claims represents the ID Token claims supported by the server.
